/*© 2010-2011 mOcean Mobile. A subsidiary of Mojiva, Inc. All Rights Reserved.*/
package com.adserver.adview;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.cache.CacheResponseStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.ContentEncodingHttpClient;
import org.apache.http.impl.client.cache.CacheConfig;
import org.apache.http.impl.client.cache.CachingHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;

public class AdServerRequest {
    private CachingHttpClient cachingClient;

    private static AdServerRequest instance;

    public static String getUserAgent() {
        return "Apache-HttpClient (java 1.5)";
    }

    public AdServerRequest() {
        CacheConfig cacheConfig = new CacheConfig();
        cacheConfig.setMaxCacheEntries(1000);
        cacheConfig.setMaxObjectSizeBytes(8192);
        cacheConfig.setSharedCache(false);
        cachingClient = new CachingHttpClient(new ContentEncodingHttpClient(), cacheConfig);
    }

    public void releaseResources() {
        cachingClient.getConnectionManager().shutdown();
        instance = null;
    }

    public static synchronized AdServerRequest getInstance() {
        if (instance == null) {
            instance = new AdServerRequest();
        }
        return instance;
    }

    public String processGetRequest(String url) throws IOException {
        BasicHttpContext localContext = new BasicHttpContext();
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        HttpGet httpGet = new HttpGet(url);
        return cachingClient.execute(httpGet, responseHandler, localContext);
    }

    public String processGetRequestEx(String url) throws IOException {
        BasicHttpContext localContext = new BasicHttpContext();
        HttpGet get = new HttpGet(url);
        HttpConnectionParams.setConnectionTimeout(cachingClient.getParams(), 10000);
        HttpConnectionParams.setSoTimeout(cachingClient.getParams(), 10000);
        HttpResponse response = cachingClient.execute(get, localContext);
        HttpEntity entity = response.getEntity();
        InputStream inputStream = entity.getContent();
        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
        String responseValue = readInputStream(bufferedInputStream);
        bufferedInputStream.close();
        inputStream.close();

        // used http://hc.apache.org/httpcomponents-client-ga/tutorial/html/caching.html
        // may be used Ehcache and memcached implementations
        EntityUtils.consume(entity);
        CacheResponseStatus responseStatus =
                (CacheResponseStatus) localContext.getAttribute(CachingHttpClient.CACHE_RESPONSE_STATUS);
        switch (responseStatus) {
            case CACHE_HIT:
                Logger.getInstance().logText(Level.INFO,
                        "A response was generated from the cache with no requests sent upstream");
                break;
            case CACHE_MODULE_RESPONSE:
                Logger.getInstance().logText(Level.INFO,
                        "The response was generated directly by the caching module");
                break;
            case CACHE_MISS:
                Logger.getInstance().logText(Level.INFO,
                        "The response came from an upstream server");
                break;
            case VALIDATED:
                Logger.getInstance().logText(Level.INFO,
                        "The response was generated from the cache after validating the entry with the origin server");
                break;
        }

        return responseValue;
    }

    private String readInputStream(BufferedInputStream in) throws IOException {
        StringBuffer out = new StringBuffer();
        byte[] buffer = new byte[1024];
        for (int n; (n = in.read(buffer)) != -1;) {
            out.append(new String(buffer, 0, n));
        }
        return out.toString();
    }
}